package fr.asip.cps3.exemple.modele;

import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;

import javax.swing.JMenuItem;

import fr.asip.cps3.exemple.vues.menus.ItemMenu;
import fr.asip.cps3.exemple.vues.menus.ItemMenuCheckbox;
import fr.asip.cps3.exemple.vues.menus.Menu;

/**
 * Le Menu
 *
 */
public class MenuApplication {

	/* Détermine si le menu doit obéir à la logique PKCS#11 en activant que progressivement les menus */
	private static boolean menuVerrouille = true;	
	
	/*
	 * Constantes désignant les identifiants des menus et items de menus 
	 */
	
	//######################//
	//  Fonctions PKCS#11   //
	//######################//
	public static final String P11 = "0";
	
	//##############//
	//  Générales   //
	//##############//
	public static final String P11_GENERAL = "0,0";
	public static final String P11_GENERAL_INITLIB = "0,0,0";
	public static final String P11_GENERAL_TERMINLIB = "0,0,1";
	public static final String P11_GENERAL_INFOLIB = "0,0,2";
	
	//###################//
	//  Slots & Cartes   //
	//###################//
	public static final String P11_SLOTSCARTES = "0,1";
	public static final String P11_SLOTSCARTES_LISTER = "0,1,0";
	public static final String P11_SLOTSCARTES_LISTER_TOUS = "0,1,0,0";
	public static final String P11_SLOTSCARTES_LISTER_AVECCARTES = "0,1,0,1";
	public static final String P11_SLOTSCARTES_INFOSLOT = "0,1,1";
	public static final String P11_SLOTSCARTES_INFOCARTE = "0,1,2";
	public static final String P11_SLOTSCARTES_ATTENTEEVNTSLOT = "0,1,3";
	public static final String P11_SLOTSCARTES_ATTENTEEVNTSLOT_BLOQUE = "0,1,3,0";
	public static final String P11_SLOTSCARTES_ATTENTEEVNTSLOT_DEBLOQUE = "0,1,3,1";
	public static final String P11_SLOTSCARTES_LISTERALGOCARTE = "0,1,4";
	public static final String P11_SLOTSCARTES_INFOALGO = "0,1,5";
	public static final String P11_SLOTSCARTES_INITPIN = "0,1,6";
	public static final String P11_SLOTSCARTES_MODIFPIN = "0,1,7";	

	//#############//
	//  Sessions   //
	//#############//
	public static final String P11_SESSIONS = "0,2";
	public static final String P11_SESSIONS_OUVRIR = "0,2,0";
	public static final String P11_SESSIONS_OUVRIR_LECTSEULE = "0,2,0,0";
	public static final String P11_SESSIONS_OUVRIR_LECTECRIT = "0,2,0,1";
	public static final String P11_SESSIONS_INFO = "0,2,1";
	public static final String P11_SESSIONS_FERMER = "0,2,2";
	public static final String P11_SESSIONS_FERMER_TOUTES = "0,2,3";
	public static final String P11_SESSIONS_AUTHENT = "0,2,4";
	public static final String P11_SESSIONS_AUTHENT_UTILISATEUR = "0,2,4,0";
	public static final String P11_SESSIONS_AUTHENT_SO = "0,2,4,1";
	public static final String P11_SESSIONS_DECONNECTE = "0,2,5";

	//###########//
	//  Objets   //
	//###########//
	public static final String P11_OBJETS = "0,3";
	public static final String P11_OBJETS_GESTION = "0,3,0";
	public static final String P11_OBJETS_GESTION_CREER = "0,3,0,0";
	public static final String P11_OBJETS_GESTION_CREER_SURCARTE = "0,3,0,0,0";
	public static final String P11_OBJETS_GESTION_COPIER = "0,3,0,1";
	public static final String P11_OBJETS_GESTION_COPIER_SURCARTE = "0,3,0,1,0";
	public static final String P11_OBJETS_GESTION_SUPPR = "0,3,0,2";
	public static final String P11_OBJETS_GESTION_SUPPR_SURCARTE = "0,3,0,2,0";
	public static final String P11_OBJETS_GESTION_TAILLE = "0,3,0,3";
	public static final String P11_OBJETS_GESTION_TAILLE_SURCARTE = "0,3,0,3,0";
	public static final String P11_OBJETS_GESTION_AFFICHEATTRIBUT = "0,3,0,4";
	public static final String P11_OBJETS_GESTION_AFFICHEATTRIBUT_SURCARTE = "0,3,0,4,0";
	public static final String P11_OBJETS_GESTION_MODIFATTRIBUT = "0,3,0,5";
	public static final String P11_OBJETS_GESTION_MODIFATTRIBUT_SURCARTE = "0,3,0,5,0";
	public static final String P11_OBJETS_RECHERCHE = "0,3,1";
	public static final String P11_OBJETS_RECHERCHE_CERTIFICATS = "0,3,1,0";
	public static final String P11_OBJETS_RECHERCHE_CLEPUBLIQUE = "0,3,1,1";
	public static final String P11_OBJETS_RECHERCHE_CLEPRIVEE = "0,3,1,2";
	public static final String P11_OBJETS_RECHERCHE_OBJETS = "0,3,1,3";
	
	//###############//
	//  Empreintes   //
	//###############//
	public static final String P11_EMPREINTES = "0,4";
	public static final String P11_EMPREINTES_MESSAGE = "0,4,0";
	public static final String P11_EMPREINTES_FICHIER = "0,4,1";
	
	//###############//
	//  Signatures   //
	//###############//
	public static final String P11_SIGNATURES = "0,5";
	public static final String P11_SIGNATURES_MESSAGE = "0,5,0";
	public static final String P11_SIGNATURES_FICHIER = "0,5,1";
	
	//####################################//
	//  Vérification de données signées   //
	//####################################//
	public static final String P11_VERIFICATIONS = "0,6";
	public static final String P11_VERIFICATIONS_MESSAGE = "0,6,0";
	public static final String P11_VERIFICATIONS_FICHIER = "0,6,1";
	
	//#########################//
	//  Génération Aléatoire   //
	//#########################//
	public static final String P11_GENERATION = "0,7";
	public static final String P11_GENERATION_NORMALE = "0,7,0";
	public static final String P11_GENERATION_SEED = "0,7,1";
	
	//###########################//
	//  Traitement Specifiques   //
	//###########################//
	public static final String TRAITEMENTSSPECIFIQUES = "1";
	public static final String TRAITEMENTSSPECIFIQUES_AUTHENTIFICATION = "1,0";
	public static final String TRAITEMENTSSPECIFIQUES_AUTHENTIFICATION_ETATCONNEXION = "1,0,0";
	public static final String TRAITEMENTSSPECIFIQUES_AUTHENTIFICATION_ASSISTAUTHENT = "1,0,1";
	public static final String TRAITEMENTSSPECIFIQUES_AUTHENTIFICATION_RETRAITCARTE = "1,0,2";
	public static final String TRAITEMENTSSPECIFIQUES_AUTHENTIFICATION_RETRAITLECTEUR = "1,0,3";
	public static final String TRAITEMENTSSPECIFIQUES_PIN = "1,1";
	public static final String TRAITEMENTSSPECIFIQUES_PIN_ETATSAISIE = "1,1,0";
	public static final String TRAITEMENTSSPECIFIQUES_PIN_RECYCLAGE = "1,1,1";
	public static final String TRAITEMENTSSPECIFIQUES_JETONS = "1,2";
	public static final String TRAITEMENTSSPECIFIQUES_JETONS_LECTURE = "1,2,0";
	public static final String TRAITEMENTSSPECIFIQUES_JETONS_MODIFICIATION = "1,2,1";	
	
	//#############//
	//  Sessions   //
	//#############//
	public static final String SESSIONS = "2";
	
	//############//
	//  Options   //
	//############//
	public static final String OPTIONS = "3";
	public static final String OPTIONS_CHARGELIB = "3,0";
	public static final String OPTIONS_DEVERROUILLER_MENU = "3,1";

	/**
	 * Ensemble des éléments constituant le menu de l'application
	 */
	private TreeMap<String,JMenuItem> itemsMenus = new TreeMap<String,JMenuItem>();
	
	/**
	 * Constructeur sans argument
	 */
	public MenuApplication() {}

	/**
	 * Initialise les menus
	 */
	public void initMenus(Application application) {
		
		if(application != null) {
		
			if(itemsMenus == null)
				itemsMenus = new TreeMap<String,JMenuItem>();		
		
			// Construction des menus basé sur le fichier de properties
			
			Properties props = application.getFichierProperties();
			if(props != null) {
			
				Set<Object> cles = props.keySet();
				
				// On itère sur toutes les clés du fichier de configuration pour isoler celles qui nous intéresse
				for (Iterator<Object> iterator = cles.iterator(); iterator.hasNext();) {
					
					// La clé
					String cle = (String) iterator.next();
					
					// Tout menu/item doit avoir un parent, même non renseigné
					if(cle.contains(".parent")) {
						
						// Récupération de l'identifiant du menu/item
						String id = cle.substring(0,cle.indexOf(".parent"));
						
						if(id != null) {
							
							// récupération des éléments nécessaires à la construction du menu/item
							String parent = (String) props.getProperty(id+".parent");
							String type = (String) props.getProperty(id+".type");
							String libelle = (String) props.getProperty(id+".libelle");
							boolean actif = Boolean.parseBoolean((String)props.getProperty(id+".actif"));
							boolean visible = Boolean.parseBoolean((String)props.getProperty(id+".visible"));
							
							// construction du menu/item
							if(parent != null && type != null && libelle != null) {
								
								if("menu".equalsIgnoreCase(type)) {
									
									if(parent != null && parent.length() == 0)
										// cas racine
										itemsMenus.put(id,new Menu(id,null,libelle,actif,visible));
									else
										// cas normal
										itemsMenus.put(id,new Menu(id,parent,libelle,actif,visible));
									
								} else if("item".equalsIgnoreCase(type)){
									
									if(parent != null && parent.length() == 0)
										// cas racine
										itemsMenus.put(id,new ItemMenu(id,null,libelle,actif,visible));
									else
										// cas normal
										itemsMenus.put(id,new ItemMenu(id,parent,libelle,actif,visible));
									
								} else if("checkbox".equalsIgnoreCase(type)){
								
									if(parent != null && parent.length() == 0)
										// cas racine
										itemsMenus.put(id,new ItemMenuCheckbox(id,null,libelle,actif,visible));
									else
										// cas normal
										itemsMenus.put(id,new ItemMenuCheckbox(id,parent,libelle,actif,visible));
								}
								
							}
						}					
					}
				}
			}
		}			
	}
	
	/**
	 * Accesseur
	 * @return Ensemble des éléments constituant le menu de l'application
	 */
	public TreeMap<String, JMenuItem> getItemsMenus() {
		return itemsMenus;
	}
	
	/**
	 * Mutateur
	 * @param itemsMenus Ensemble des éléments constituant le menu de l'application
	 */
	public void setItemsMenus(TreeMap<String, JMenuItem> itemsMenus) {
		this.itemsMenus = itemsMenus;
	}

	/**
	 * Ajoute des éléments à l'ensemble des éléments constituant le menu de l'application
	 * @param nouveauxItemsMenus Ensemble d'éléments à ajouter
	 */
	public void addItemsMenus(TreeMap<String, JMenuItem> nouveauxItemsMenus) {
		this.itemsMenus.putAll(nouveauxItemsMenus);
	}

	/**
	 * Ajoute un menu à l'ensemble des éléments constituant le menu de l'application
	 * @param menu Menu à ajouter
	 */
	public void ajouteMenu(Menu menu) {
		
		if(itemsMenus == null)
			itemsMenus = new TreeMap<String, JMenuItem>();
		
		Menu parent = (Menu)this.itemsMenus.get(menu.getIdParent());
		if(parent != null) {
			this.itemsMenus.put(menu.getId(),menu);
			parent.add(menu);
		}
		
	}

	/**
	 * Ajoute un item de menu à l'ensemble des éléments constituant le menu de l'application
	 * @param itemMenu Item de menu à ajouter
	 */
	public void ajouteItemMenu(ItemMenu itemMenu) {
		
		if(itemsMenus == null)
			itemsMenus = new TreeMap<String, JMenuItem>();
			
		Menu parent = (Menu)this.itemsMenus.get(itemMenu.getIdParent());
		if(parent != null) {
			this.itemsMenus.put(itemMenu.getId(),itemMenu);
			parent.add(itemMenu);
		}
		
	}	
	
	/**
	 * Supprime un menu de l'ensemble des éléments constituant le menu de l'application
	 * @param menu Menu à supprimer
	 */
	public void supprimeMenu(Menu menu) {
		
		if(itemsMenus != null) {
			Menu parent = (Menu)this.itemsMenus.get(menu.getIdParent());
			parent.remove(menu);
			this.itemsMenus.remove(menu.getId());
		}
		
	}	
	


	/**
	 * Supprime une item de menu de l'ensemble des éléments constituant le menu de l'application
	 * @param itemMenu Item de menu à supprimer
	 */
	public void supprimeItemMenu(ItemMenu itemMenu) {
		
		if(itemsMenus != null) {
			Menu parent = (Menu)this.itemsMenus.get(itemMenu.getIdParent());
			parent.remove(itemMenu);
			this.itemsMenus.remove(itemMenu.getId());
		}
		
	}

	/**
	 * Supprime le contenu d'un sous menu
	 * @param idMenu Identifiant du sous menu dont il faut supprimer le contenu
	 */
	public void supprimeContenuMenu(String idMenu) {
		
		if(itemsMenus != null) {
			Menu menu = (Menu)this.itemsMenus.get(idMenu);
			if(menu != null)
				menu.removeAll();
		}
		
	}	
	
	/**
	 * Active un menu
	 * @param idMenu Identifiant du menu à activer
	 */
	public void setItemMenuActif(String idMenu) {

		if(itemsMenus != null && this.itemsMenus.get(idMenu) != null) {
			if(isMenuVerrouille())
				((JMenuItem)this.itemsMenus.get(idMenu)).setEnabled(true);
			if(this.itemsMenus.get(idMenu) instanceof ItemMenu)
				((ItemMenu)this.itemsMenus.get(idMenu)).setActif(true);
			else if(this.itemsMenus.get(idMenu) instanceof Menu)
				((Menu)this.itemsMenus.get(idMenu)).setActif(true);
		}

		
	}

	/**
	 * Désactive un menu
	 * @param idMenu Identifiant du menu à désactiver
	 */
	public void setItemMenuNonActif(String idMenu) {
		
		if(itemsMenus != null && this.itemsMenus.get(idMenu) != null) {
			if(isMenuVerrouille())
				((JMenuItem)this.itemsMenus.get(idMenu)).setEnabled(false);
			if(this.itemsMenus.get(idMenu) instanceof ItemMenu)
				((ItemMenu)this.itemsMenus.get(idMenu)).setActif(false);
			else if(this.itemsMenus.get(idMenu) instanceof Menu)
				((Menu)this.itemsMenus.get(idMenu)).setActif(false);
		}
		
	}

	/**
	 * Accesseur
	 * Détermine si le menu doit obéir à la logique PKCS#11 en activant que progressivement les menus
	 * @return true ou false
	 */
	public static boolean isMenuVerrouille() {
		return menuVerrouille;
	}

	/**
	 * Mutateur
	 * Affecte le booléen qui étermine si le menu doit obéir à la logique PKCS#11 en activant que progressivement les menus
	 * @param true ou false
	 */
	public static void setMenuVerrouille(boolean menuVerrouille) {
		MenuApplication.menuVerrouille = menuVerrouille;
	}
	
}
